Ziva Vatra - home :: Projects :: Audio :: Media Player :: Mark II
Linux Based standalone multiformat player

Linux Based Streaming Media Player - Mark II

Back in the mid 00's, I tried to make a standalone Media player, the goal being to have a quiet unobtrusive PC that can play compressed media (such as MP3 CDs) while looking like any other piece of Hi-Fi equipment. For reasons detailed at the top of the Mark I article, this project was never completed despite a lot of work put into it. While I thought I would make a second attempt shortly after that failure, the reality is that I am only now considering it in 2018, 11 years after the original failed.

Many reasons for not doing it come to mind, but one reason that came to mind for trying the project again was the introduction of the Raspberry Pi. The first SBC that is easily available to retail users. This SBC is silent by design, draws very little power, and comes with proper GPIO ports (no more interfacing with a PC parallel port). Also I was in a position where my HiFi was not near enough my workstation for me to hook them up together, so a standalone media player would once again be useful.

Also while moving house, I found my old Nokia Mediamaster digibox. UK residents will remember these when the goverment was trying to get everyone to switch to digital TV broadcasts so they could auction off the analogue TV channels for big money. An organisation called "onDigital" gave people these Nokia digital set-top boxes for free so that people could still use their old TVs. We got one, and it all worked well when they switched off the analoge signals.

However a couple of years later, we got to experience a new joy of digital TV: Forced obsolescence. An update to the digital TV signals rendered all these old boxes unusable. Despite functioning perfectly, they were now nothing more than doorstops. As a result many of them ended up in the trash (and everyone had to buy new digital receivers), while our one got relegated to the attic where it was forgotten about.

Fast forward a few years, and I came across it again, more or less pristine but useless. However it was designed to fit in a living room, so it fit the bill and I decided to use that as my case for the new media centre.

The world has changed since my last attempt at this project. For one thing with the improvement in home networking and internet speeds, mp3CDs are no longer that popular. I don't have many, and those I do have are mostly for the car CD player. I store all my music on my server and I listen to online radio stations, so the goal of this project is primarily to handle streaming media from the network, with CD playing being the secondary task.

The Plan

The initial plan for this project is as follows (in order of importance):

  1. To give good quality audio output
  2. To be easy to use to play audio streams from my collection or the internet
  3. To be silent in operation and not draw a lot of power
  4. To not look out of place in the living room next to the Hi-Fi
  5. Have a remote interface for control
  6. Support playing of audio and data CDs with compressed audio on them

Prototyping

With that plan in mind I go to work. I removed the innards of the Nokia, put in a 2 line VFD (temporarily duct taped to the front panel), the raspberry pi and installed Rasbpian on it. I had an old USB "Sound Blaster" sound card in my junk box, so that got repurposed to provide some higher quality audio output than the built in pi's audio. Truth be told it all seemed so simple compared to the "Mark I" that I didn't even consider a write up and I did not take photos.

After all there was so much space in the case, the pi was so small and the VFD was plug-and-play (being serial based it only needed three wires and me to configure the tty attributes for it to work) it didn't feel like a write up would contribute much.

However with time and testing, some flaws came about in the prototype which needed to be remedied, specifically:

  • It had no interface, I would use ncmpc on my workstation or laptop to control it
  • The Raspberry pi would randomly reset, especially when trying to update the DB
  • The Raspberry pi only had 256MB of RAM and a single core, and the mpd client I wrote in Python was very bloated (by virtue of being written in Python). As a result after some time of use the pi would end up running out of RAM and swapping, which would cause the audio to stutter and the pi to become unresponsive.

The issue of not having an interface was actually not solved by me. I found out that there was an excellent Android application, called "mpdDroid" that allowed me to make use of a smartphone to control the player. I had an old Android phone that was no longer in use, so that was repurposed as the remote control. This also meant that I did not have to develop my own electronic interface (I had considered interfacing some buttons for basic control, and deploying LIRC for remote control).

With mpdroid, the prototype actually became very useful, and I started using it more and more. As such I considered the idea worth doing properly and as a result the project (and this write up) was born.

Solving the flaws

The first flaw I had to deal with was the bloated VFD client. Python used too much RAM, and it took too long to start up for the task it had to do. So I decided to re-write the client in C. Good practice for me (as I rarely use C anymore) and it solved my RAM issue. With the new "C" based client, the overhead was low enough that both it and mpd can share the CPU with the OS without causing audio stuttering or other problems. Now the system could reliably play music without issue.

The second flaw I had to deal with was the indexing of the mpd database. Even with my new C client, I found that mpd would run out of RAM if it tried to index my entire music collection. If you used swap it would crawl for so long that it could take more than a day to index the DB, and during that time the player was unusable. After much research and investigation, there seemed no way I could improve on the situation. I even looked at whether it was possible to index the DB offline on my server, and just have mpd on the pi read the db, but this wasn't supported by mpd. At the end I felt I had two options going forward: I could either modify mpd to support external DB indexing, or I just buy a more powerful pi.

I decided to do the latter and duly bought a raspberry pi 2. It has 1GB of RAM, which should be more than enough for our needs, and it also has 4 cores. I felt it would be better to upgrade the pi because even if I did write the software for offline mpd DB indexing, there is no guarantee that down the line something else will consume all the RAM and cause issues. Fact is 256MB of RAM is not that much anymore, and Linux gets more bloated every year (I remember when an entire Linux distro could fit on a floppy drive and run in 16MB of RAM).

Plus if I ever wanted to add features to the system, I may again find myself without enough RAM, or too many processes fighting over the single CPU. Audio streaming is latency sensitive, interruptions can cause jitter and stuttering, so I felt it better if I could dedicate a single CPU to mpd, and a single CPU to the VFD client. With 4 CPUs on the pi2 I can do that, and also have two CPUs free for background and OS tasks.

Now we have three of the flaws resolved, but the resets persisted. In fact it had gotten worse with 4 cores and higher clock speed. With time I noticed the resets seemed to be related to load. The longer the pi was under load, the more likely it would eventually reset. I suspected a poor PSU (that is normally the issue with pi's), but replacing that with a more powerful version didn't help.

Next thing I suspected was that it was overheating. So to find out I wrote a program that printed the CPU speed and temperature on the VFD, like so:

The good thing with using the VFD is that it would keep its state as long as it had power, even if the pi died, so with a 1 second update I would get the last second temperature before the pi stopped responding. I didn't have to monitor it, but just put it under load, went to do something else and see when the music stops I would go and read the data on the VFD.

Sure enough, the temperature was high just before it reset, 87°C. the pi CPU was only rated to around 85C, so presumably there is some kind of thermal cut off if it exceeds this. I was surprised it got this hot, considering that while it was inside a case, the case itself was well vented, roomy and without any other heat generating systems nearby.

Whatever the reasons, the solution seems to be "better cooling". I looked online and there were loads of little "pi fan and heatsink" combos out there to buy. However I wanted to keep this system fanless, both from a noise and maintenance perspective. Also many of the systems on offer were designed to fit in standard pi cases so they had to compromise with a fan for added airflow or a very small heatsink, while I had a lot more free space to play with.

So I rummaged around my junk box for a suitable heatsink, and found an old ASUS motherboard northbridge heatsink. It looked perfect for the job, and even looked quite snazzy in its blue anodised aluminium. Making it fit the pi however, required some work on my milling table. First thing I did was level off the base:

Then I had to work out which bits to mill away so it could fit on the pi. This was tricky as I needed it to rest on the CPU/GPU and any other bits that could do with cooling without shorting anything out. I found out that it only needed milling out three notches and some of the fins in order to clear the USB/ethernet ports on the pi's edge. Here are the notches milled:

And the fin on the bottom milled for the USB/Eth ports:

And the heatsink attached to the pi for test fitment (hence still has some swarf on it). It is probably the only "ASUS" branded Raspberry pi on the Internet :-)

I found that the heatsink compound I used is itself sticky enough to keep the heatsink firmly attached to the pi, so I didn't have to worry about screwing or gluing it down (after all this will go into a system that will hardly ever move). All in all it was a success, the random hangs/resets had gone and in the case under full load the CPU temp did not go over 55°C.

Further improvements

With the flaws sorted, I could work towards properly fitting everything in the case. First thing I did was get some scrap acrylic and drill out locations for PCB standoffs. These were then used to mount the pi securely to the acrylic.

As I also wanted a to include a CD-ROM drive I bought a proper 5V 5A PSU, which should provide enough power for the pi, the USB sound card and CD-ROM combined. This too was fitted to the acrylic as shown below (without the heatsink yet attached on the pi):

Next step was to find a way to mount the VFD so it sat flush near the front of the case (the Nokia has a nice tinted transparent section where the old 7 segment LED display was). To do this I made a top-section out of 5mm acrylic I had in my junk box from an old project, and holes were tapped for two long screws that attach the side of the sheet to the VFD.

The plan was for this to sit on top of the pi, so a section was milled out for the heatsink to pass through for cooling:

Once mounted as shown below, the VFD was attached to the top sheet, which itself was attached to the bottom sheet with a single spring loaded screw. This allowed for fine tuning the display orientation along the horizontal plane. The VFD is able pivot up and down, and by turning the screw you can set it in the ideal position for visibility.

And everying in place and cleaned up with the heatsink attached. There is good clearance so there should be no impact on airflow and cooling with this set up.

With all this complete, the system was re-assembled and tested. I am happy to report that everything works flawlessly, and after a couple of weeks of testing, it was moved to sit on the top of the Hi-Fi:

Top left is the Sound blaster USB sound card, and to the right of it is my DAC. At the moment I use the analogue of the sound card but it supports SPDIF out so in future I can connect it to the DAC directly. As for the display, the current VFD is laid out as follows:

It is relatively simple, allows for long elapsed times and playlists and conveys the information needed. The top line was designed to scroll forwards/backwards if the line is longer than the VFD (sounds simple, but it actually took a lot of racking of the brain when I wrote the code for this part).

With that, I've done all I wanted to do with this project. I will now make use of the system and see how things progress.

Update: February 2022

System has worked flawlessly over the last couple of years. During that time I found out that my internet radio app, "RadioDroid" supports mpd! This means that I can use it to play internet radio streams on my media player as well on my phone. It really is well integrated now.

In addition to the "remote control" phone, I also have both apps on my main phone. Coupled with PC based mpd clients I know multiple different controls simultaniously, no more having to "find the remote".

However two issues were discovered. First the PSU has gotten noisy as time has passed. I think one of the inductors has started buzzing. The system still works but it is too noisy to be in my living room, so after another rummage in my junk box I found an old PSU from a USB hub, 3A at 5V, which should be good enough in the interim:

In the photo above you can see it mounted where the old PSU was. The plug was removed and replaced with connectors to the back of the case. I also took the advantage of having the system apart, and I replaced the external sound card with a new internal USB->SPDIF card which is mounted to the rear of the case as well.

From now on the system will play through my standalone DAC. That is likely to provide the best quality of the options available to me, plus I don't have to worry about clean and filtered power supplies or EMF isolation in order to minimise noise entering the analogue audio stram. The system can be pure digital and the analogue is handled by the DAC which is designed for it.

The second issue I discovered is that the underside of the Nokia case had scratched the top of my control amplifier. This is a good demonstration of why Hi-Fi separates systems come with feet. I could not fit proper Hi-fi feet to this case, but I found some other rubber feet that I attached which at least prevent any further damage.

Towards the rear of the photo you can see the CD-ROM drive. I have not mentioned it much so far because nothing has been done with it. It is a laptop CD-ROM drive in a USB->IDE external case. It is connected to the pi, but I have done no work on integrating it into the system. Since I built this system I have not had the need to use a single CD with it. I can play my entire FLAC/MP3/etc... collection through streaming, and if I really want to listen to a physical CD I have a dedicated CD player for that.
It doesn't help that MPD is very clunky when it comes to supporting audio CDs, involving trying to get digital audio extraction to work and then having to add tracks as songs in the playlist. It would take a lot of work to get it working smoothly. Even for CD's with compressed audio on them, getting Linux to auto-mount a data CD and auto-add it to mpd would require custom code, which I am not sure is worth it unless I will use the feature often.

Either way, that is it for this update, lets see how long until the next one :-)

Page created: Fri Aug 24 11:03:47 2018 ][ Page last modified: Sun Feb 27 19:04:00 2022 ]